#pragma once
#include <functional>
#include "Connect.hpp"
#include "NonBlock.hpp"
#include "Log.hpp"
#include "Format.hpp"
#include "Reactor.hpp"

namespace NormalConnectModule
{
    using namespace ConnectModule;
    using namespace NonBlockModule;
    using namespace LogModule;
    using namespace ReactorModule;
    using namespace FormatModule;
    using work_t = std::function<std::string(std::string &)>;
    class NormalConnect : public Connect
    {
        const static int size = 1024;

    public:
        NormalConnect(int fd)
        {
            NonBlock::SetNonBlock(fd);
            SetFd(fd);
            SetEvents(EPOLLIN | EPOLLET);
            FormatModule::Format format;
            _format_data = [&format](std::string& buf) {
                return format.HandlerRequest(buf);
            };
        }
        virtual void Send() override
        { 
            while (true)
            {
                ssize_t n = send(Fd(), _outbuff.c_str(), _outbuff.size(), 0);
                if (n > 0)
                {
                    // 成功
                    _outbuff.erase(0, n); // 移除N个
                }
                else if (n == 0)
                {
                    break;
                }
                else
                {
                    if (errno == EAGAIN || errno == EWOULDBLOCK)
                    {
                        // 缓冲区写满了，下次再来
                        break;
                    }
                    else if (errno == EINTR)
                    {
                        continue;
                    }
                    else
                    {
                        Except();
                        return;
                    }
                }
            }
            if (!_outbuff.empty())
            {
                // 修改对sockfd的事件关心！-- 开启对写事件关心
                // 按需设置！
                Owner()->EnableReadWrite(Fd(), true, true);
            }
            else
            {
                Owner()->EnableReadWrite(Fd(), true, false);
            }
        }
        virtual void Recv() override
        {
            // 非阻塞循环读
            while (true)
            {
                char buffer[size];
                ssize_t s = recv(Fd(), buffer, sizeof(buffer) - 1, 0);
                if (s > 0)
                {
                    buffer[s] = 0;
                    // 读取成功了
                    _inbuff += buffer;
                }
                if (s == 0)
                {
                    // 对端关闭连接
                    Except();
                    return;
                }
                else
                {
                    if (errno == EAGAIN || errno == EWOULDBLOCK)
                    {
                        break;
                    }
                    else if (errno == EINTR)
                    {
                        continue;
                    }
                    else
                    {
                        // 出错
                        Except();
                        break;
                    }
                }
            }
            _outbuff += _format_data(_inbuff);
            // 利用该机制使得write动作的文件描述符自动完成
            if (!_outbuff.empty())
            {
                Owner()->EnableReadWrite(Fd(), true, true);
            }
        }
        virtual void Except() override
        {
            LOG(LogLevel::INFO) << "客户端连接可能结束，进行异常处理: " << Fd();
            Owner()->RemoveConnection(Fd());
        }
        virtual ~NormalConnect()
        {
        }

    private:
        // 对应的输入、输出、异常缓冲区
        std::string _inbuff;
        std::string _outbuff;
        std::string _exceptbuff;
        // 定制协议的格式化数据
        work_t _format_data;
    };
}